﻿//----------------------------------------------------------------------------------------------------
// The IAIPlayer is the base class for all AI types
//----------------------------------------------------------------------------------------------------

package HG.AI
{
	import HG.Events.NodeEvent;
	import HG.Events.LevelEvent;
	
	import HG.Visual.VisualNode;
	
	import HG.Actions.IAction;
	
	import HG.GameService;
	import HG.Managers.LevelManager;
	import HG.Managers.ActionManager;
	import HG.Managers.ResourceManager;
	import HG.Managers.NodeManager;
	import HG.Managers.TurnManager;
	import HG.Debug;
	import HG.Managers.BindingManager;
	import HG.Managers.PlayerManager;
	import HG.Managers.NotificationManager;
	import HG.Managers.GameRuleManager;
	
	public class SentryPlayer extends IAIPlayer
	{
		var m_levelManager:LevelManager;
		var m_actionManager:ActionManager;
		var m_resourceManager:ResourceManager;
		var m_turnManager:TurnManager;
		var m_bindingManager:BindingManager;
		var m_playerManager:PlayerManager;
		var m_notificationManager:NotificationManager;
		var m_gameRuleManager:GameRuleManager;
		
		var m_rootNode:Number;
		var m_targetNode:Number;
		var m_targetPlayer:Number;
		
		var m_targetingPlayer:Boolean;
		
		var m_path:Array;
		var m_currentPathNode:Number;
		
		var m_aggressive:Boolean;
		
		//----------------------------------------------------------------------------------------------------
		public function SentryPlayer(ID:Number)
		{
			super(ID);
			
			m_levelManager = GameService.GetInstance().GetLevelManager();
			m_actionManager = GameService.GetInstance().GetActionManager();
			m_resourceManager = GameService.GetInstance().GetResourceManager();
			m_turnManager = GameService.GetInstance().GetTurnManager();
			m_bindingManager = GameService.GetInstance().GetBindingManager();
			m_playerManager = GameService.GetInstance().GetPlayerManager();
			m_notificationManager = GameService.GetInstance().GetNotificationManager();
			m_gameRuleManager = GameService.GetInstance().GetGameRuleManager();
			
			
			m_levelManager.addEventListener(LevelEvent.LOAD, OnLevelLoadComplete);
			
			m_bindingManager.RegisterBinding("TripSentry", TripSentry);
			
			m_targetingPlayer = false;
		}
		
		//----------------------------------------------------------------------------------------------------
		public override function OnTick(DeltaTime:Number)
		{
		}
		
		//----------------------------------------------------------------------------------------------------
		public override function SetActive(active:Boolean)
		{
			super.SetActive(active);
			
			m_gameRuleManager.RaiseGameUpdateEvent();
		}
		
		//----------------------------------------------------------------------------------------------------
		public override function GetTurnsToReachPlayer():Number
		{
			if (!m_active)
				return 0;
				
			if (!m_aggressive)
				return 0;
				
			if (!m_targetingPlayer)
				return 0;
				
			return m_currentPathNode + 1;
		}
		
		//----------------------------------------------------------------------------------------------------
		public function TripSentry(targetNode:Number, targetPlayer:Number)
		{
			// Cannot trip self.
			if (m_playerID == targetPlayer)
				return;
			
			// Cannot re-trip
			if (m_aggressive)
				return;
				
			var playerRoot:Number = m_playerManager.GetPlayer(targetPlayer).GetRootNode();
			if (targetNode == playerRoot)
				m_targetingPlayer = true;
			
			m_aggressive = true;
			
			m_targetNode = targetNode;
			m_targetPlayer = targetPlayer;
			
			m_path = m_levelManager.GetPathBetween(m_rootNode, m_targetNode);
			m_currentPathNode = m_path.length - 2; // correct for 0-index, and dont count the last node (its myself)
			
			m_notificationManager.RaiseNotification("SENTRY ONLINE");
			m_gameRuleManager.RaiseGameUpdateEvent();
		}
		
		//----------------------------------------------------------------------------------------------------
		// External events
		//----------------------------------------------------------------------------------------------------
		private function OnLevelLoadComplete(evt:LevelEvent)
		{
			// Get initial nod elsit form level manager.
			var myNodes:Array = m_levelManager.GetVisualNodesOcupiedByPlayer(m_playerID);
			
			Debug.ASSERT(myNodes.length == 1, "Sentry AI must start with a single node!");
			
			m_rootNode = myNodes[0];
		}
		
		//----------------------------------------------------------------------------------------------------
		// Perform actions is the AI's turn to lodge actions for the next turn. return true when ready.
		//----------------------------------------------------------------------------------------------------
		public override function PerformActions()
		{
			if (!m_active)
				return;
				
			if (!m_aggressive)
				return;
				
				
			// Get a new path.
			if (m_currentPathNode < 0)
			{
				var newTargetNode:Number = m_playerManager.GetPlayer(m_targetPlayer).GetRootNode();
				
				m_path = m_levelManager.GetPathBetween(m_targetNode, newTargetNode);
				
				// If the new path is too short to be valid, then we won!
				if (m_path.length <= 1)
				{
					m_aggressive = false;
					SetActive(false);
					return;
				}
			
				m_targetNode = newTargetNode;
				m_currentPathNode = m_path.length - 1;
				
				m_targetingPlayer = true;
			}
			
			if (m_currentPathNode < 0)
				return;
			
			var targetNode:VisualNode = m_path[m_currentPathNode];
			if (!targetNode)
				return;
			
			// Perform path
			do
			{
				targetNode = m_path[m_currentPathNode];
				m_currentPathNode--;
			}
			while (targetNode.GetIsOcupiedBy(m_playerID));
			
			Debug.ASSERT(targetNode.GetType() != NodeManager.NODE_SENTRY, "Sentry path to sentry node!");
			
			var action:IAction = m_actionManager.CreateAction(
				ActionManager.ACTION_HACK, 
				m_playerID,
				targetNode.GetID());
			
			m_turnManager.AddPendingAction(action);
			
			m_gameRuleManager.RaiseGameUpdateEvent();
		
		}
		
		//----------------------------------------------------------------------------------------------------
	}
}
